#include <iostream>
#include <string>
#include <memory>

class Fruit
{
public:
    virtual void name() = 0;
};

class Apple : public Fruit
{
public:
    void name() override
    {
        std::cout << "这是一个苹果" << std::endl;
    }
};

class Pear : public Fruit
{
public:
    void name() override
    {
        std::cout << "这是一个梨" << std::endl;
    }
};

class Animal
{
public:
    virtual void name() = 0;
};

class Cat : public Animal
{
public:
    void name() override
    {
        std::cout << "一只小猫~" << std::endl;
    }
};

class Sheep : public Animal
{
public:
    void name() override
    {
        std::cout << "一只小绵羊~" << std::endl;
    }
};

// 抽象工厂模式:超级工厂生产子类工厂, 再有子类工厂生产产品.
class Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name) = 0;
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name) = 0;
};

class FruitFactory : public Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name)
    {
        if (name == "苹果")
            return std::make_shared<Apple>();
        return std::make_shared<Pear>();
    };
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name)
    {
        return std::shared_ptr<Animal>();
    }
};

class AnimalFactory : public Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name)
    {
        return std::shared_ptr<Fruit>();
    };
    virtual std::shared_ptr<Animal> getAnimal(const std::string &name)
    {
        if (name == "猫")
            return std::make_shared<Cat>();
        return std::make_shared<Sheep>();
    }
};

// 超级工厂
class FactoryProducer
{
public:
    static std::shared_ptr<Factory> create(const std::string &name)
    {
        if (name == "水果")
            return std::make_shared<FruitFactory>();
        return std::make_shared<AnimalFactory>();
    }
};
int main()
{
    std::shared_ptr<Factory> factory = FactoryProducer::create("水果");
    std::shared_ptr<Fruit> fruit = factory->getFruit("苹果");
    fruit->name();
    fruit = factory->getFruit("梨");
    fruit->name();
    factory = FactoryProducer::create("动物");
    std::shared_ptr<Animal> animal = factory->getAnimal("猫");
    animal->name();
    animal = factory->getAnimal("羊");
    animal->name();
    return 0;
}